#include <iostream>
#include <pthread.h>
#include <string>
#include <unistd.h>
using namespace std;

struct th_data
{
    string _name;
    int _tickets = 1000;
    pthread_mutex_t* _mtx;

    th_data(const string& name, int tickets, pthread_mutex_t* mtx) 
        : _name(name), _tickets(tickets), _mtx(mtx)
    {}
};

void* thread_run(void* args)
{
    th_data* td = static_cast<th_data*>(args);
    while (true)
    {
        pthread_mutex_lock(td->_mtx);

        if (td->_tickets > 0)
        {
            usleep(1000);
            cout << td->_name << " get a ticket " << td->_tickets-- << endl;
            pthread_mutex_unlock(td->_mtx);
        }
        else 
        {
            pthread_mutex_unlock(td->_mtx);
            break;
        }

        usleep(500);
    }

    return nullptr;
}

int main()
{
    pthread_mutex_t mutex;
    pthread_mutex_init(&mutex, nullptr);

    pthread_t t[4];
    int n = sizeof(t)/sizeof(pthread_t);

    for (int i = 0; i < n; i++) 
    {
        string name = "thread-" + to_string(i);
        th_data* td = new th_data(name, 1000, &mutex);
        pthread_create(&t[i], nullptr, thread_run, (void*)td);
    }

    for (int i = 0; i < n; i++)
    {
        pthread_join(t[i], nullptr);
    }

    pthread_mutex_destroy(&mutex);

    return 0;
}
